<?php

namespace core;

class Router
{
    protected string $controller = 'app\controller\HomeController'; // 默认控制器
    protected string $method = 'index'; // 默认方法
    protected array $params = [];

    public function __construct()
    {
        $this->parseUrl();
    }

    /**
     * 解析 URL
     * URL 格式: /controller/method/param1/param2/...
     */
    protected function parseUrl(): void
    {
        $url      = $_GET['url'] ?? '';
        $url      = filter_var(trim($url, '/'), FILTER_SANITIZE_URL);
        $urlParts = $url ? explode('/', $url) : [];

        // 1. 获取控制器
        if (!empty($urlParts[0])) {
            // 将 controller-name 转换为 ControllerName
            $controllerName = str_replace('-', '', ucwords($urlParts[0], '-')) . 'Controller';
            $controllerFile = APP_PATH . '/controller/' . $controllerName . '.php';
            
            // **安全检查**：检查文件是否存在
            if (file_exists($controllerFile)) {
                $this->controller = 'app\\controller\\' . $controllerName;
                unset($urlParts[0]);
            }
        }

        // 2. 获取方法
        if (!empty($urlParts[1])) {
            $methodName = $urlParts[1];
            // **安全检查**：我们将在 dispatch 中使用 method_exists()
            // 避免调用如 __construct 这样的魔术方法
            if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $methodName) && strpos($methodName, '__') !== 0) {
                $this->method = $methodName;
                unset($urlParts[1]);
            }
        }

        // 3. 获取参数
        $this->params = $urlParts ? array_values($urlParts) : [];
    }

    /**
     * 调度请求
     */
    public function dispatch(): void
    {
        // **安全检查**：检查类是否存在
        if (!class_exists($this->controller)) {
            throw new \Exception("Controller class not found: {$this->controller}");
        }

        $controllerInstance = new $this->controller;

        // **安全检查**：检查方法是否存在且是公开的
        if (!is_callable([$controllerInstance, $this->method])) {
            throw new \Exception("Method not found or not callable: {$this->method} in {$this->controller}");
        }

        // 使用 PHP 8 的 call_user_func_array (尽管 spread ... 运算符更好)
        // call_user_func_array 更适合动态参数列表
        call_user_func_array([$controllerInstance, $this->method], $this->params);
    }
}